package server

import (
	"context"
	"fmt"
	"glmall-product/internal/conf"
	"net/http"
	"strings"

	consul "github.com/go-kratos/kratos/contrib/registry/consul/v2"
	"github.com/go-kratos/kratos/v2/registry"
	"github.com/go-kratos/kratos/v2/transport/grpc"
	"github.com/google/wire"
	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
	consulAPI "github.com/hashicorp/consul/api"
	"golang.org/x/net/http2"
	"golang.org/x/net/http2/h2c"
)

// ProviderSet is server providers.
var ProviderSet = wire.NewSet(NewGRPCServer, NewHTTPServer, NewRegistrar)

func NewRegistrar(conf *conf.Registry) registry.Registrar {
	if conf == nil {
		fmt.Println("registry config is nil")
	}
	if conf.Consul == nil {
		fmt.Println("consul config is nil")
	}
	if conf.Consul.Address == "" {
		fmt.Println("consul address is empty")
	}
	c := consulAPI.DefaultConfig()
	c.Address = conf.Consul.Address
	c.Scheme = conf.Consul.Scheme
	cli, err := consulAPI.NewClient(c)
	if err != nil {
		panic(err)
	}
	// // 3. 配置服务注册信息
	// registration := &consulAPI.AgentServiceRegistration{
	// 	Name:    "glmall-product",
	// 	Address: "127.0.0.1",
	// 	Port:    8004,
	// }

	// if err := cli.Agent().ServiceRegister(registration); err != nil {
	// 	panic(fmt.Sprintf("failed to register service: %v", err))
	// }

	r := consul.New(cli,
		consul.WithHealthCheck(false), // 禁用 Kratos 默认的健康检查（使用自定义的 Check）
	)
	return r
}

type HosServer struct {
	httpSvr *runtime.ServeMux
	grpcSvr *grpc.Server
	c       *conf.Server
}

// Start starts the server.
func (s *HosServer) Start(ctx context.Context) error {
	fmt.Println("Start HosServer Addr: " + s.c.Http.Addr)
	err := http.ListenAndServe(
		s.c.Http.Addr,
		grpcHandlerFunc(s.grpcSvr, s.httpSvr),
	)
	if err != nil {
		return err
	}
	return nil
}

// Stop stops the server.
func (s *HosServer) Stop(ctx context.Context) error {
	return nil
}

func NewHosServer(c *conf.Server, httpSvr *runtime.ServeMux, grpcSvr *grpc.Server) *HosServer {
	return &HosServer{
		httpSvr: httpSvr,
		grpcSvr: grpcSvr,
		c:       c,
	}
}

// grpcHandlerFunc 根据请求头判断是grpc请求还是grpc-gateway请求
func grpcHandlerFunc(grpcServer *grpc.Server, otherHandler http.Handler) http.Handler {
	return h2c.NewHandler(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.ProtoMajor == 2 && strings.Contains(r.Header.Get("Content-Type"), "application/grpc") {
			grpcServer.ServeHTTP(w, r)
		} else {
			otherHandler.ServeHTTP(w, r)
		}
	}), &http2.Server{})
}
